package com.xuecheng.checkcode.service;

import com.xuecheng.base.exception.XueChengPlusException;
import com.xuecheng.checkcode.model.CheckCodeParamsDto;
import com.xuecheng.checkcode.model.CheckCodeResultDto;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;

/**
 * 验证码接口
 */
@Slf4j
public abstract class AbstractCheckCodeService implements CheckCodeService {

    protected CheckCodeGenerator checkCodeGenerator;    // 验证码生成器
    protected KeyGenerator keyGenerator;                // key生成器
    protected CheckCodeStore checkCodeStore;            // 验证码存储

    public abstract void setCheckCodeGenerator(CheckCodeGenerator checkCodeGenerator);

    public abstract void setKeyGenerator(KeyGenerator keyGenerator);

    public abstract void setCheckCodeStore(CheckCodeStore CheckCodeStore);


    /**
     * 生成验证码公用方法
     *
     * @param checkCodeParamsDto 生成验证码参数
     * @param code_length        验证码长度
     * @param keyPrefix          key的前缀
     * @param expire             过期时间
     * @return 生成结果
     */
    public GenerateResult generate(CheckCodeParamsDto checkCodeParamsDto, Integer code_length, String keyPrefix, Integer expire) {
        // 生成四位验证码
        String code = checkCodeGenerator.generate(code_length);
        log.debug("生成验证码:{}", code);
        // 生成一个key
        String key = keyGenerator.generate(keyPrefix);

        // 存储验证码到Redis中
        checkCodeStore.set(key, code, expire);
        // 返回验证码生成结果
        GenerateResult generateResult = new GenerateResult();
        generateResult.setKey(key);
        generateResult.setCode(code);
        return generateResult;
    }

    /**
     * 验证码生成结果
     */
    @Data
    protected class GenerateResult {
        String key;
        String code;
    }


    /**
     * 验证码生成
     *
     * @param checkCodeParamsDto 生成验证码参数
     * @return 验证码结果dto
     */
    public abstract CheckCodeResultDto generate(CheckCodeParamsDto checkCodeParamsDto);


    /**
     * 校验验证码
     *
     * @param key  键
     * @param code 验证码
     * @return 验证成功：true，验证失败：false
     */
    public boolean verify(String key, String code) {
        // key键 或 验证码为空
        if (StringUtils.isBlank(key) || StringUtils.isBlank(code)) {
            return false;
        }
        // 根据key，从redis中获取正确验证码
        String code_l = checkCodeStore.get(key);
        // 获取失败
        if (code_l == null) {
            return false;
        }
        // 验证码比对（忽略大小写）
        boolean result = code_l.equalsIgnoreCase(code);
        // 比对成功
        if (result) {
            // 从redis中删除验证码
            checkCodeStore.remove(key);
        }
        // 返回结果
        return result;
    }


}
